﻿using AntMovement.Core.IParameter;
using AntMovement.Core.Logic.Base;
using Prism.Ioc;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace AntMovement.WPF.Resources.Controls
{
    [TemplatePart(Name = AirCylinderControlPartName, Type = typeof(SingleControl))]
    public class AirCylinderControl : ContentControl, INotifyPropertyChanged
    {
        public const string AirCylinderControlPartName = "PART_AirCylinderControl";
        private IAirCylinder _ac;

        public IAirCylinder AC
        {
            get { return _ac; }
            set { SetProperty(ref _ac, value); }
        }
        private IContainerProvider _containerProvider;
        public AirCylinderControl()
        {
            _containerProvider = ContainerLocator.Container;
            #region 基础
            Binding bindingName = new Binding();
            bindingName.Source = this;
            bindingName.Path = new PropertyPath("AC.Name");
            bindingName.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
            BindingOperations.SetBinding(this, AirCylinderControl.TitleProperty, bindingName);

            Binding bindingReach_Open = new Binding();
            bindingReach_Open.Source = this;
            bindingReach_Open.Path = new PropertyPath("AC.Reach_Open");
            bindingReach_Open.Mode = BindingMode.OneWay;
            BindingOperations.SetBinding(this, AirCylinderControl.Reach_OpenProperty, bindingReach_Open);

            Binding bindingReach_Close = new Binding();
            bindingReach_Close.Source = this;
            bindingReach_Close.Path = new PropertyPath("AC.Reach_Close");
            bindingReach_Close.Mode = BindingMode.OneWay;
            BindingOperations.SetBinding(this, AirCylinderControl.Reach_CloseProperty, bindingReach_Close);

            Binding bindingAlarm = new Binding();
            bindingAlarm.Source = this;
            bindingAlarm.Path = new PropertyPath("AC.Alarm");
            bindingAlarm.Mode = BindingMode.OneWay;
            BindingOperations.SetBinding(this, AirCylinderControl.AlarmProperty, bindingAlarm);

            Binding bindingOpen = new Binding();
            bindingOpen.Source = this;
            bindingOpen.Path = new PropertyPath("AC.Manual_Open");
            bindingOpen.Mode = BindingMode.TwoWay;
            bindingOpen.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
            BindingOperations.SetBinding(this, AirCylinderControl.OpenProperty, bindingOpen);

            Binding bindingClose = new Binding();
            bindingClose.Source = this;
            bindingClose.Path = new PropertyPath("AC.Manual_Close");
            bindingClose.Mode = BindingMode.TwoWay;
            bindingClose.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
            BindingOperations.SetBinding(this, AirCylinderControl.CloseProperty, bindingClose);
            #endregion


            Binding bindingIn_OpenName = new Binding();
            bindingIn_OpenName.Source = this;
            bindingIn_OpenName.Path = new PropertyPath("AC.In_OpenName");
            bindingIn_OpenName.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
            BindingOperations.SetBinding(this, AirCylinderControl.In_OpenNameProperty, bindingIn_OpenName);

            Binding bindingIn_CloseName = new Binding();
            bindingIn_CloseName.Source = this;
            bindingIn_CloseName.Path = new PropertyPath("AC.In_CloseName");
            bindingIn_CloseName.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
            BindingOperations.SetBinding(this, AirCylinderControl.In_CloseNameProperty, bindingIn_CloseName);

            Binding bindingOut_OpenName = new Binding();
            bindingOut_OpenName.Source = this;
            bindingOut_OpenName.Path = new PropertyPath("AC.Out_OpenName");
            bindingOut_OpenName.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
            BindingOperations.SetBinding(this, AirCylinderControl.Out_OpenNameProperty, bindingOut_OpenName);

            Binding bindingOut_CloseName = new Binding();
            bindingOut_CloseName.Source = this;
            bindingOut_CloseName.Path = new PropertyPath("AC.Out_CloseName");
            bindingOut_CloseName.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
            BindingOperations.SetBinding(this, AirCylinderControl.Out_CloseNameProperty, bindingOut_CloseName);
        }

        static AirCylinderControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(AirCylinderControl), new FrameworkPropertyMetadata(typeof(AirCylinderControl)));
        }
        #region 依赖属性
        public string Title
        {
            set => SetValue(TitleProperty, value);
            get => GetValue(TitleProperty) as string;
        }

        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title", typeof(string), typeof(AirCylinderControl), new FrameworkPropertyMetadata("名字"));

        public static DependencyProperty UpdateBindProperty = DependencyProperty.RegisterAttached("UpdateBind", typeof(bool), typeof(AirCylinderControl), new PropertyMetadata(false, UpdateBindChanged));

        public bool UpdateBind
        {
            get => (bool)GetValue(UpdateBindProperty);
            set => SetValue(UpdateBindProperty, value);
        }

        private static void UpdateBindChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            AirCylinderControl control = d as AirCylinderControl;
            if (control == null)
            {
                return;
            }
            if (e.NewValue is Boolean bl && bl)
            {
                control.SetObject(control.Title);
            }
        }

        public void SetObject(string title)
        {
            AC = _containerProvider.Resolve<IIOParameter>().GetAirCylinder(title);
        }

        public string In_OpenName
        {
            get { return (string)GetValue(In_OpenNameProperty); }
            set { SetValue(In_OpenNameProperty, value); }
        }

        public static readonly DependencyProperty In_OpenNameProperty =
            DependencyProperty.Register(nameof(In_OpenName), typeof(string), typeof(AirCylinderControl), new PropertyMetadata(string.Empty));

        public string Out_OpenName
        {
            get { return (string)GetValue(Out_OpenNameProperty); }
            set { SetValue(Out_OpenNameProperty, value); }
        }

        public static readonly DependencyProperty Out_OpenNameProperty =
            DependencyProperty.Register(nameof(Out_OpenName), typeof(string), typeof(AirCylinderControl), new PropertyMetadata(string.Empty));

        public string In_CloseName
        {
            get { return (string)GetValue(In_CloseNameProperty); }
            set { SetValue(In_CloseNameProperty, value); }
        }

        public static readonly DependencyProperty In_CloseNameProperty =
            DependencyProperty.Register(nameof(In_CloseName), typeof(string), typeof(AirCylinderControl), new PropertyMetadata(string.Empty));



        public string Out_CloseName
        {
            get { return (string)GetValue(Out_CloseNameProperty); }
            set { SetValue(Out_CloseNameProperty, value); }
        }

        public static readonly DependencyProperty Out_CloseNameProperty =
            DependencyProperty.Register(nameof(Out_CloseName), typeof(string), typeof(AirCylinderControl), new PropertyMetadata(string.Empty));

        public bool Alarm
        {
            get { return (bool)GetValue(AlarmProperty); }
            set { SetValue(AlarmProperty, value); }
        }
        public static readonly DependencyProperty AlarmProperty =
            DependencyProperty.Register(nameof(Alarm), typeof(bool), typeof(AirCylinderControl), new PropertyMetadata(false));

        public static readonly DependencyProperty OpenProperty
    = DependencyProperty.Register(nameof(Open), typeof(bool?), typeof(AirCylinderControl),
        new FrameworkPropertyMetadata(default(bool?)));
        public bool? Open
        {
            get => (bool?)GetValue(OpenProperty);
            set => SetValue(OpenProperty, value);
        }

        public static readonly DependencyProperty CloseProperty
            = DependencyProperty.Register(nameof(Close), typeof(bool?), typeof(AirCylinderControl),
                new FrameworkPropertyMetadata(default(bool?)));
        public bool? Close
        {
            get => (bool?)GetValue(CloseProperty);
            set => SetValue(CloseProperty, value);
        }

        public bool Reach_Open
        {
            get { return (bool)GetValue(Reach_OpenProperty); }
            set { SetValue(Reach_OpenProperty, value); }
        }

        public static readonly DependencyProperty Reach_OpenProperty =
            DependencyProperty.Register(nameof(Reach_Open), typeof(bool), typeof(AirCylinderControl), new PropertyMetadata(false));

        public bool Reach_Close
        {
            get { return (bool)GetValue(Reach_CloseProperty); }
            set { SetValue(Reach_CloseProperty, value); }
        }

        public static readonly DependencyProperty Reach_CloseProperty =
            DependencyProperty.Register(nameof(Reach_Close), typeof(bool), typeof(AirCylinderControl), new PropertyMetadata(false));


        #endregion

        #region 事件通知
        bool SetProperty<T>(ref T member, T value, [CallerMemberName] string? propertyName = null)
        {
            if (EqualityComparer<T>.Default.Equals(member, value))
            {
                return false;
            }

            member = value;
            OnPropertyChanged(propertyName);
            return true;
        }

        public event PropertyChangedEventHandler? PropertyChanged;
        void OnPropertyChanged([CallerMemberName] string? propertyName = null)
            => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        #endregion
    }
}